home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 235 / Issue 235 - September 2007 - DPCS0907DVD.ISO / Microsoft / Expression Blend / Blend.en.msi / Sparkle.PBook.Book.xaml.cs.en < prev    next >
Encoding:
Text File  |  2007-03-29  |  36.5 KB  |  552 lines

  1.  ■using System;
  2. using System.IO;
  3. using System.Net;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Data;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Imaging;
  10. using System.Windows.Media.Animation;
  11. using System.Windows.Navigation;
  12. using System.Collections.Generic;
  13. using System.Collections.ObjectModel;
  14. using System.Xml.Serialization;
  15. namespace PhotoBook
  16. {
  17.     public partial class BookViewer
  18.     {
  19.         ImageCollection collection = null;
  20.         // Number of the page on the right.
  21.         Int32 currentPage;
  22.         // Width and Height of the first image loaded.
  23.         Double pageWidth;
  24.         Double pageHeight;
  25.         // Start value for the angle of page turning.
  26.         Double angle = 45;
  27.         // Value of the X position to be used to calculate the angle of the page turning.
  28.         Double referenceX;
  29.         Double mouseX, mouseY;
  30.         #region Initialization
  31.         public BookViewer()
  32.         {
  33.             this.InitializeComponent();
  34.         }
  35.         protected override void OnInitialized(EventArgs e)
  36.         {
  37.             base.OnInitialized(e);
  38.         }
  39.         /// <summary>
  40.         /// BookPathProperty is exposed on Expression Blend under the Miscellaneous category in the Properties panel.
  41.         /// </summary>
  42.         public string BookPath
  43.         {
  44.             get { return (string)base.GetValue(BookPathProperty); }
  45.             set
  46.             {
  47.                 base.SetValue(BookPathProperty, value);
  48.                 this.InitPages();
  49.             }
  50.         }
  51.         public static readonly DependencyProperty BookPathProperty = DependencyProperty.Register("BookPath", typeof(string), typeof(BookViewer), new PropertyMetadata(new PropertyChangedCallback(HandleBookPathChanged)));
  52.         public void InitPages()
  53.         {
  54.             collection = new ImageCollection();
  55.             collection.Location = this.BookPath;
  56.             HideShadowMiddle();
  57.             this.LoadPages();
  58.         }
  59.         private static void HandleBookPathChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
  60.         {
  61.             ((BookViewer)source).InitPages();
  62.         }
  63.         #endregion
  64.         #region Load Pages
  65.         /// <summary>
  66.         /// Pages are loaded dynamically when they will be visible.
  67.         /// Odd pages are on the right and even pages are on the left.
  68.         /// </summary>
  69.         public void LoadPages()
  70.         {
  71.             if (this.collection.Images.Count == 0)
  72.                 return;
  73.             if (currentPage == 0)
  74.             {
  75.                 // If it's the first page only three pages are loaded, since the book is closed.
  76.                 HideShadowEven();
  77.                 HideShadowMiddle();
  78.                 pageEvenTop.Opacity = 0;
  79.                 LoadOddTopPage(collection.Images[currentPage]);
  80.                 LoadEvenBottomPage(collection.Images[currentPage + 1]);
  81.                 LoadOddBottomPage(collection.Images[currentPage + 2]);
  82.             }
  83.             else
  84.             {
  85.                 // Otherwise load four pages per each page turn.
  86.                 // Two pages on top and two pages at the bottom.
  87.                 ShowShadowMiddle();
  88.                 pageEvenTop.Opacity = 1;
  89.                 LoadOddTopPage(collection.Images[currentPage]);
  90.                 LoadEvenTopPage(collection.Images[currentPage - 1]);
  91.                 LoadEvenBottomPage(collection.Images[currentPage + 1]);
  92.                 LoadOddBottomPage(collection.Images[currentPage + 2]);
  93.                 InitPageEvenTop(pageEvenTop);
  94.             }
  95.         }
  96.         public void LoadEvenBottomPage(String page)
  97.         {
  98.             Uri uri = new Uri(System.IO.Path.Combine("file://", page));
  99.             BitmapImage bitmap = new BitmapImage(uri);
  100.             pageEvenBottom.Source = bitmap;
  101.             pageEvenBottom.Loaded += new RoutedEventHandler(PageEvenBottom_Loaded);
  102.         }
  103.         public void LoadEvenTopPage(String page)
  104.         {
  105.             Uri uri = new Uri(System.IO.Path.Combine("file://", page));
  106.             BitmapImage bitmap = new BitmapImage(uri);
  107.             pageEvenTop.Source = bitmap;
  108.             pageEvenTop.Loaded += new RoutedEventHandler(PageEvenTop_Loaded);
  109.         }
  110.         public void LoadOddBottomPage(String page)
  111.         {
  112.             Uri uri = new Uri(System.IO.Path.Combine("file://", page));
  113.             BitmapImage bitmap = new BitmapImage(uri);
  114.             pageOddBottom.Source = bitmap;
  115.             pageOddBottom.Loaded += new RoutedEventHandler(PageOddBottom_Loaded);
  116.         }
  117.         public void LoadOddTopPage(String page)
  118.         {
  119.             Uri uri = new Uri(System.IO.Path.Combine("file://", page));
  120.             BitmapImage bitmap = new BitmapImage(uri);
  121.             pageOddTop.Source = bitmap;
  122.             pageOddTop.Loaded += new RoutedEventHandler(PageOddTop_Loaded);
  123.         }
  124.         /// <summary>
  125.         /// Initializes the attributes, based on the bottom page on the left (even page).
  126.         /// </summary>
  127.         void PageEvenBottom_Loaded(object sender, RoutedEventArgs e)
  128.         {
  129.             FrameworkElement img = sender as FrameworkElement;
  130.             img.Width = pageWidth;
  131.             img.Height = pageHeight;
  132.             pageEvenBottomRotate.CenterX = 0;
  133.             pageEvenBottomRotate.CenterY = pageHeight;
  134.             pageEvenBottomRotate.Angle = angle * 2;
  135.             pageEvenBottomTranslate.X = pageWidth * 2;
  136.             clipEvenBottomRotate.CenterX = pageWidth;
  137.             clipEvenBottomRotate.CenterY = pageHeight;
  138.             clipEvenBottomRotate.Angle = 45;
  139.             clipEvenBottomTranslate.X = pageWidth;
  140.             shadowEven.Height = pageHeight * 2;
  141.             shadowEven.Width = pageWidth;
  142.             shadowEvenTranslate.X = pageWidth;
  143.             shadowEvenTranslateX.Y = -pageHeight / 2;
  144.             shadowEvenRotate.CenterX = pageWidth;
  145.             shadowEvenRotate.CenterY = pageHeight;
  146.             shadowEvenRotate.Angle = angle;
  147.             clipShadowEvenRotate.CenterX = 0;
  148.             clipShadowEvenRotate.CenterY = pageHeight;
  149.             clipShadowEvenRotate.Angle = angle * 2;
  150.             clipShadowEvenTranslate.X = pageWidth * 2;
  151.             shadowOdd.Height = pageHeight;
  152.             shadowOdd.Width = pageWidth;
  153.             shadowOddRotate.CenterY = pageHeight;
  154.             shadowOddRotate.Angle = 45;
  155.             shadowOddTranslate.X = pageWidth;
  156.             shadowEvenMiddle.Height = pageHeight;
  157.             shadowOddMiddle.Height = pageHeight;
  158.             UpdateClipArea("evenBottom");
  159.         }
  160.         void PageEvenTop_Loaded(object sender, RoutedEventArgs e)
  161.         {
  162.             InitPageEvenTop(sender);
  163.         }
  164.         void PageOddBottom_Loaded(object sender, RoutedEventArgs e)
  165.         {
  166.             FrameworkElement img = sender as FrameworkElement;
  167.             pageWidth = img.ActualWidth;
  168.             pageHeight = img.ActualHeight;
  169.             clipOddBottomRotate.CenterX = 0;
  170.             clipOddBottomRotate.CenterY = pageHeight;
  171.             clipOddBottomRotate.Angle = angle;
  172.             clipOddBottomTranslate.X = pageWidth;
  173.             UpdateClipArea("oddBottom");
  174.         }
  175.         void PageOddTop_Loaded(object sender, RoutedEventArgs e)
  176.         {
  177.             FrameworkElement img = sender as FrameworkElement;
  178.             pageWidth = img.ActualWidth;
  179.             pageHeight = img.ActualHeight;
  180.             backShadowOdd.Height = pageHeight + 2;
  181.             backShadowOdd.Width = pageWidth + 2;
  182.             backShadowOdd2.Height = pageHeight + 4;
  183.             backShadowOdd2.Width = pageWidth + 4;
  184.             backShadowOdd3.Height = pageHeight + 6;
  185.             backShadowOdd3.Width = pageWidth + 6;
  186.             backShadowOdd4.Height = pageHeight + 8;
  187.             backShadowOdd4.Width = pageWidth + 8;
  188.         }
  189.         void InitPageEvenTop(object sender)
  190.         {
  191.             FrameworkElement img = sender as FrameworkElement;
  192.             img.Width = pageWidth;
  193.             img.Height = pageHeight;
  194.             UpdateClipArea("evenTop");
  195.         }
  196.         #endregion
  197.         #region Drag Page
  198.         /// <summary>
  199.         /// This event is raised by the top page on the right (odd page), defined in XAML.
  200.         /// </summary>
  201.         private void OnStartDrag(object sender, MouseEventArgs e)
  202.         {
  203.             if (currentPage < collection.Images.Count - 2)
  204.             {
  205.                 FrameworkElement el = sender as FrameworkElement;
  206.                 el.CaptureMouse();
  207.                 Point mousePos = Mouse.GetPosition(pageOddTop);
  208.                 UpdateMousePos();
  209.                 el.MouseMove += new MouseEventHandler(UpdateMouseMove);
  210.             }
  211.         }
  212.         /// <summary>
  213.         /// This event is raised by the top page on the left (even page).
  214.         /// </summary>
  215.         private void OnStartDragBack(object sender, MouseEventArgs e)
  216.         {
  217.             if(currentPage > 1)
  218.             {
  219.                 currentPage -= 2;
  220.                 LoadPages();
  221.                 angle = 0;
  222.                 UpdatePageOddTurning();
  223.                 bookShadow.Opacity = 0.5;
  224.             }
  225.             FrameworkElement el = sender as FrameworkElement;
  226.             el.CaptureMouse();
  227.             Point mousePos = Mouse.GetPosition(pageOddTop);
  228.             UpdateMousePos();
  229.             el.MouseMove += new MouseEventHandler(UpdateMouseMove);
  230.         }
  231.         private void OnStopDrag(object sender, MouseEventArgs e)
  232.         {
  233.             AnimFinishPageTurn();
  234.             FrameworkElement el = sender as FrameworkElement;
  235.             el.ReleaseMouseCapture();
  236.             pageOddTop.MouseLeave -= new MouseEventHandler(OnHideFold);
  237.             el.MouseMove -= new MouseEventHandler(UpdateMouseMove);
  238.         }
  239.         private void OnStopDragBack(object sender, MouseEventArgs e)
  240.         {
  241.             FrameworkElement el = sender as FrameworkElement;
  242.             el.ReleaseMouseCapture();
  243.             el.MouseMove -= new MouseEventHandler(UpdateMouseMoveBack);
  244.         }
  245.         #endregion
  246.         #region CLIP Methods
  247.         private void OnUpdateClipArea(object sender, SizeChangedEventArgs e)
  248.         {
  249.             UpdateClipArea("oddBottom");
  250.         }
  251.         /// <summary>
  252.         /// Updates the mask effect of the pages.
  253.         /// </summary>
  254.         private void UpdateClipArea(String whichClip)
  255.         {
  256.             Point p1, p2;
  257.             Rect clipArea;
  258.             switch (whichClip)
  259.             {
  260.                 case "oddBottom":
  261.                     p1 = new Point(0, -pageHeight);
  262.                     p2 = new Point(pageWidth, pageHeight * 2);
  263.                     clipArea = new Rect(p1, p2);
  264.                     clipOddBottom.Rect = clipArea;
  265.                     break;
  266.                 case "evenBottom":
  267.                     p1 = new Point(0, -pageHeight);
  268.                     p2 = new Point(pageWidth, pageHeight);
  269.                     clipArea = new Rect(p1, p2);
  270.                     clipEvenBottom.Rect = clipArea;
  271.                     p1 = new Point(0, 0);
  272.                     p2 = new Point(pageWidth, pageHeight);
  273.                     clipArea = new Rect(p1, p2);
  274.                     clipShadowEven.Rect = clipArea;
  275.                     p1 = new Point(0, -pageWidth);
  276.                     p2 = new Point(pageWidth * 2, pageHeight);
  277.                     clipArea = new Rect(p1, p2);
  278.                     clipShadowOdd.Rect = clipArea;
  279.                     break;
  280.                 case "evenTop":
  281.                     p1 = new Point(0, 0);
  282.                     p2 = new Point(pageWidth, pageHeight);
  283.                     clipArea = new Rect(p1, p2);
  284.                     clipEvenTop.Rect = clipArea;
  285.                     break;
  286.                 default:
  287.                     break;
  288.             }
  289.         }
  290.         #endregion
  291.         #region Shadow Methodos
  292.         /// <summary>
  293.         /// This section updates the shadow effect under the pages.
  294.         /// It also controls the shadow and highlight of the folder on the middle.
  295.         /// </summary>
  296.         private void HideShadowEven()
  297.         {
  298.             backShadowEven.Visibility = Visibility.Hidden;
  299.             backShadowEven2.Visibility = Visibility.Hidden;
  300.             backShadowEven3.Visibility = Visibility.Hidden;
  301.             backShadowEven4.Visibility = Visibility.Hidden;
  302.         }
  303.         private void ShowShadowEven()
  304.         {
  305.             backShadowEven.Visibility = Visibility.Visible;
  306.             backShadowEven2.Visibility = Visibility.Visible;
  307.             backShadowEven3.Visibility = Visibility.Visible;
  308.             backShadowEven4.Visibility = Visibility.Visible;
  309.         }
  310.         private void HideShadowMiddle()
  311.         {
  312.             middleShadow.Visibility = Visibility.Hidden;
  313.         }
  314.         private void ShowShadowMiddle()
  315.         {
  316.             middleShadow.Visibility = Visibility.Visible;
  317.         }
  318.         private void SetOpacityShadowEven(Double opc)
  319.         {
  320.             backShadowEven.Opacity = opc;
  321.             backShadowEven2.Opacity = opc;
  322.             backShadowEven3.Opacity = opc;
  323.             backShadowEven4.Opacity = opc;
  324.         }
  325.         #endregion
  326.         #region Page Turn Methdos
  327.         /// <summary>
  328.         /// When the page is released, verify what direction the page should go.
  329.         /// </summary>
  330.         private void AnimFinishPageTurn()
  331.         {
  332.             if (angle < 15)
  333.             {
  334.                 // If the angle is small, complete the page turn.
  335.                 angle = 0;
  336.                 ShowShadowEven();
  337.             }
  338.             else
  339.             {
  340.                 // If the angle is not small enough, turn it back to the initial position.
  341.                 angle = 45;
  342.                 currentPage -= 2;
  343.             }
  344.             GetNextPhotos();
  345.             UpdatePageOddTurning();
  346.         }
  347.         private void GetNextPhotos()
  348.         {
  349.             if (currentPage < collection.Images.Count - 2) currentPage += 2;
  350.             if (currentPage < collection.Images.Count - 2)
  351.             {
  352.                 bookShadow.Opacity = 1;
  353.                 LoadPages();
  354.                 angle = 45;
  355.             }
  356.         }
  357.         /// <summary>
  358.         /// Calculates the position X that is used to update the angle of the page.
  359.         /// </summary>
  360.         private void CalculatePositionX()
  361.         {
  362.             Double perc = 100 * angle / 45;
  363.             Double newX = pageWidth * perc / 100;
  364.             referenceX = newX;
  365.         }
  366.         /// <summary>
  367.         /// Show a fold at the corner of the page, indicating that there are more pages behind.
  368.         /// </summary>
  369.         private void OnShowFold(object sender, MouseEventArgs e)
  370.         {
  371.             if (currentPage < collection.Images.Count - 2)
  372.             {
  373.                 angle = 40;
  374.                 UpdatePageOddTurning();
  375.             }
  376.         }
  377.         private void OnHideFold(object sender, MouseEventArgs e)
  378.         {
  379.             angle = 45;
  380.             UpdatePageOddTurning();
  381.         }
  382.         #endregion
  383.         #region Mouse Methods
  384.         private Point GetMouseDelta()
  385.         {
  386.             Point mousePos = Mouse.GetPosition(pageOddTop);
  387.             Double deltaX = mousePos.X - mouseX;
  388.             Double deltaY = mousePos.Y - mouseY;
  389.             Point point = new Point(deltaX, deltaY);
  390.             return point;
  391.         }
  392.         private void UpdateMousePos()
  393.         {
  394.             Point mousePos = Mouse.GetPosition(pageOddTop);
  395.             mouseX = mousePos.X;
  396.             mouseY = mousePos.Y;
  397.         }
  398.         /// <summary>
  399.         /// Main method that verifies the mouse position as it moves, updating the angle of the page.
  400.         /// </summary>
  401.         private void UpdateMouseMove(object sender, MouseEventArgs e)
  402.         {
  403.             FrameworkElement el = sender as FrameworkElement;
  404.             Point delta = GetMouseDelta();
  405.             angle += delta.X / 8;
  406.             if (angle > 45) angle = 45;
  407.             if (angle < 0) angle = 0;
  408.             UpdatePageOddTurning();
  409.             if (angle <= 5)
  410.             {
  411.                 Double opc = (50 + (angle * 10)) / 100;
  412.                 bookShadow.Opacity = opc;
  413.             }
  414.             if (currentPage == 0)
  415.             {
  416.                 if (angle <= 0.6)
  417.                 {
  418.                     ShowShadowEven();
  419.                     Double opcShadow = (6 - (angle - 0.5) * 10) / 100;
  420.                     SetOpacityShadowEven(opcShadow);
  421.                 }
  422.                 else
  423.                 {
  424.                     HideShadowEven();
  425.                 }
  426.             }
  427.             UpdateMousePos();
  428.             if (!el.IsMouseCaptured) el.ReleaseMouseCapture();
  429.         }
  430.         private void UpdateMouseMoveBack(object sender, MouseEventArgs e)
  431.         {
  432.             FrameworkElement el = sender as FrameworkElement;
  433.             Point mousePos = Mouse.GetPosition(pageOddTop);
  434.             if (!el.IsMouseCaptured) el.ReleaseMouseCapture();
  435.         }
  436.         /// <summary>
  437.         /// Based on the angle, this method updates position, rotation and masks (clips).
  438.         /// </summary>
  439.         private void UpdatePageOddTurning()
  440.         {
  441.             CalculatePositionX();
  442.             clipOddBottomRotate.Angle = angle;
  443.             clipOddBottomRotate.CenterX = (referenceX) - (pageWidth);
  444.             clipOddBottomTranslateX.X = (referenceX) - (pageWidth);
  445.             pageEvenBottomRotate.Angle = angle * 2;
  446.             pageEvenBottomRotate.CenterX = (referenceX) - (pageWidth);
  447.             pageEvenBottomTranslateX.X = (referenceX * 2) - (pageWidth * 2);
  448.             shadowEvenRotate.CenterX = (referenceX);
  449.             shadowEvenRotate.Angle = angle;
  450.             shadowEvenTranslateX.X = (referenceX) - (pageWidth);
  451.             clipShadowEvenRotate.Angle = angle * 2;
  452.             clipShadowEvenRotate.CenterX = (referenceX) - (pageWidth);
  453.             clipShadowEvenTranslateX.X = (referenceX * 2) - (pageWidth * 2);
  454.             shadowOddRotate.Angle = angle;
  455.             shadowOddRotate.CenterX = (referenceX) - (pageWidth) + 1;
  456.             shadowOddTranslateX.X = (referenceX) - (pageWidth);
  457.             clipEvenBottomRotate.Angle = angle;
  458.             clipEvenBottomTranslate.X = referenceX;
  459.         }
  460.         #endregion
  461.     }
  462. }